from django.conf import settings
from django.utils.http import int_to_base36, base36_to_int
from django.contrib.auth.tokens import PasswordResetTokenGenerator


class EmailConfirmationTokenGenerator(PasswordResetTokenGenerator):
    """
    Strategy object used to generate and check tokens for the email
    confirmation mechanism.
    """
    def check_token(self, user, token):
        """
        Check that a password reset token is correct for a given user.
        """
        # Parse the token
        try:
            ts_b36, hash = token.split("-")
        except ValueError:
            return False

        try:
            ts = base36_to_int(ts_b36)
        except ValueError:
            return False

        # Check that the timestamp/uid has not been tampered with
        if self._make_token_with_timestamp(user, ts) != token:
            return False

        # Check the timestamp is within limit
        timeout_days = getattr(settings, 'EMAIL_CONFIRMATION_TIMEOUT_DAYS', None)
        if timeout_days and (self._num_days(self._today()) - ts) > timeout_days:
            return False

        return True

    def _make_token_with_timestamp(self, user, timestamp):
        # timestamp is number of days since 2001-1-1.  Converted to
        # base 36, this gives us a 3 digit string until about 2121
        ts_b36 = int_to_base36(timestamp)

        # By hashing on the internal state of the user we produce a hash that
        # will be invalid as soon as it is used.
        # We limit the hash to 20 chars to keep URL short
        from django.utils.hashcompat import sha_constructor
        hash = sha_constructor(settings.SECRET_KEY + unicode(user.id) + user.email +
                               unicode(timestamp)).hexdigest()[::2]
        return "%s-%s" % (ts_b36, hash)

default_token_generator = EmailConfirmationTokenGenerator()
